﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Gaia.WebWidgets;
using Gaia.WebWidgets.HtmlFormatting;
using System.ComponentModel;
using System.Drawing;

[assembly: System.Web.UI.WebResource("Extension.VPort.js", "text/javascript")]
namespace Extension
{
    [System.Web.UI.ParseChildren(true)]
    [System.Web.UI.PersistChildren(false)]
    [System.Web.UI.ToolboxData("<{0}:VPort runat=\"server\"></{0}:VPort>")]
    public class VPort : HybridPanelBase, IAjaxControl, IExtraPropertyCallbackRenderer
    {

        private VPortView firstView;
        /// <summary>
        /// First ViewPortView (top or left)
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [System.Web.UI.PersistenceMode(System.Web.UI.PersistenceMode.InnerProperty)]
        [System.ComponentModel.Description("View")]
        public VPortView FirstView { get { return firstView; } set { firstView = value; } }

        private VPortView secondView;
        /// <summary>
        /// Second ViewPortView (bottom or right)
        /// </summary>
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [System.Web.UI.PersistenceMode(System.Web.UI.PersistenceMode.InnerProperty)]
        [System.ComponentModel.Description("View")]
        public VPortView SecondView { get { return secondView; } set { secondView = value; } }

        protected Panel dragger;
        protected Panel toggle;

        /// <summary>
        /// Changes visibility of ViewportViews
        /// </summary>
        [Browsable(true)]
        public bool Hidden
        {
            get 
            {
                if (ViewState["hd"] == null)
                    ViewState["hd"] = false;
                return (bool)ViewState["hd"];
            }
            set 
            {
                ViewState["hd"] = value;
                if (value)
                {
                    if (hideSecondView) onhidden = 2;
                    else onhidden = 1;
                }
                else onhidden = 0;
            }
        }

        private bool hideSecondView = true;
        /// <summary>
        /// says which ViewPortView is closable
        /// </summary>
        [Browsable(true)]
        public bool HideSecondView { get { return hideSecondView; } set { hideSecondView = value; } }

        private int dragSpace = 20;
        /// <summary>
        /// How much to the border you can drag the dragger
        /// </summary>
        [Browsable(true)]
        public int DragSpace { get { return dragSpace; } set { dragSpace = value; } }

        public enum EOrientation
        {
            Horizontal = 0,
            Vertical = 1
        }
        private EOrientation orientation = EOrientation.Horizontal;
        /// <summary>
        /// Orientation of ViewPort: Horizontal or Vertical
        /// </summary>
        [Browsable(true)]
        public EOrientation Orientation { get { return orientation; } set { orientation = value; } }
        
        public VPort()
        {
            dragger = new Panel();
            toggle = new Panel();
        }

        protected override void OnInit(EventArgs e)
        {
            // init Panels
            InitDragger();
            InitToggle();
            InitViews();
            
            base.OnInit(e);
        }

        private void InitDragger()
        {
            dragger.ID = "d";
            dragger.CssClass = Css.Combine(this.CssClass, "Dragger-" + orientation.ToString());
            dragger.Controls.Add(new System.Web.UI.LiteralControl("&nbsp;"));
            this.Controls.Add(dragger);
        }

        private void InitToggle()
        {
            toggle.ID = "t";
            toggle.CssClass = Css.Combine(this.CssClass, "Toggle-" + orientation.ToString());

            string orient = orientation == EOrientation.Horizontal ? "width" : "height";
            toggle.Style[orient] = "15px";
            toggle.Style["display"] = "none";
            toggle.Controls.Add(new System.Web.UI.LiteralControl("&nbsp;"));
            this.Controls.Add(toggle);
        }

        private void InitViews()
        {
            if (firstView != null && secondView != null)
            {
                firstView.CssClass = Css.Combine(this.CssClass, "FirstView-" + orientation.ToString());
                secondView.CssClass = Css.Combine(this.CssClass, "SecondView-" + orientation.ToString());

                firstView.ID = "FV";
                secondView.ID = "SV";

                this.Controls.Add(FirstView);
                this.Controls.Add(SecondView);                
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            AddAspects();
        }

        private void AddAspects()
        {
            if (orientation == EOrientation.Horizontal)
            {
                int width = firstView.Width + secondView.Width - 2 * dragSpace;
                dragger.Aspects.Add(new AspectDraggable(dropped, new Rectangle(dragSpace, 0, width, 0), false, true, 1M));
            }
            else
            {
                int height = firstView.Height + secondView.Height - 2 * dragSpace;
                dragger.Aspects.Add(new AspectDraggable(dropped, new Rectangle(0, dragSpace, 0, height), false, true, 1M));
            }
            toggle.Aspects.Add(new AspectClickable(Toggle_Clicked));
        }

        protected override void OnPreRender(EventArgs e)
        {
            SetWidthsHeights();
            base.OnPreRender(e);
        }
        /// <summary>
        /// For the first time ViewPortViews needs width or height to be set.
        /// </summary>
        private void SetWidthsHeights()
        {
            if (orientation == EOrientation.Horizontal && (dragger.Style["left"] == null ||
                !dragger.Style["left"].Equals(this.firstView.Width.ToString() + "px")))
            {
                dragger.Style["left"] = this.firstView.Width.ToString() + "px";
                this.firstView.Style["width"] = this.firstView.Width.ToString() + "px";
                this.secondView.Style["width"] = this.secondView.Width.ToString() + "px";
                this.Style["width"] = (this.firstView.Width + 5 + this.secondView.Width).ToString() + "px";
                this.firstView.Style["margin-left"] = "-5px";
                this.secondView.Style["margin-left"] = "5px";
            }
            else if (orientation == EOrientation.Vertical && (dragger.Style["top"] == null ||
                !dragger.Style["top"].Equals(this.firstView.Height.ToString() + "px")))
            {
                dragger.Style["top"] = this.firstView.Height.ToString() + "px";
                this.firstView.Style["height"] = this.firstView.Height.ToString() + "px";
                this.secondView.Style["height"] = this.secondView.Height.ToString() + "px";
                this.Style["height"] = (this.firstView.Height + 5 + this.secondView.Height).ToString() + "px";
                this.firstView.Style["margin-top"] = "-5px";
                this.secondView.Style["margin-top"] = "5px";
            }
        }
        /// <summary>
        /// The ViewPort has been hidden and now it's not.
        /// </summary>
        public event EventHandler Show;

        protected void Toggle_Clicked(object sender, EventArgs e)
        {
            Hidden = false;

            if (Show != null)
                Show(this, new EventArgs());
        }
        /// <summary>
        /// The Dragger has moved
        /// </summary>
        public event EventHandler Dragged;

        protected void dropped(object sender, EventArgs e)
        {
            onDropped = true;
            if (orientation == EOrientation.Horizontal)
            {
                int dragLeft = int.Parse(dragger.Style["left"].Replace("px", ""));
                int width = int.Parse(this.Style["width"].Replace("px", ""));
                this.firstView.Width = dragLeft;
                this.secondView.Width = width - dragLeft - 5;
            }
            else
            {
                int dragTop = int.Parse(dragger.Style["top"].Replace("px", ""));
                int height = int.Parse(this.Style["height"].Replace("px", ""));
                this.firstView.Height = dragTop;
                this.secondView.Height = height - dragTop - 5;
            }

            if (Dragged != null)
                Dragged(this, new EventArgs());
        }
        
        protected override void IncludeScriptFiles()
        {
            base.IncludeScriptFiles();
            Manager.Instance.AddInclusionOfFileFromResource("Extension.VPort.js", typeof(VPort), "Gaia.Extensions.VPort.browserFinishedLoading");
        }

        protected override void RenderControlHtml(Gaia.WebWidgets.HtmlFormatting.XhtmlTagFactory create)
        {
            if (firstView != null && secondView != null)
            {
                using (Tag Div = create.Div(this.ClientID, this.CssClass))
                {
                    Css.SerializeAttributesAndStyles(this, Div);

                    dragger.RenderControl(create.GetHtmlTextWriter());
                    firstView.RenderControl(create.GetHtmlTextWriter());
                    toggle.RenderControl(create.GetHtmlTextWriter());
                    secondView.RenderControl(create.GetHtmlTextWriter());
                }
            }
        }
        

        #region [ -- Overridden IAjaxControl Methods -- ]

        PropertyStateManagerControl IAjaxControl.CreateControlStateManager()
        {
            return new PropertyStateManagerWebControl(this, ClientID, this);
        }

        string IAjaxControl.GetScript()
        {
            return new RegisterControl("Gaia.Extensions.VPort", ClientID)
                .AddProperty("hide", onhidden)
                .AddProperty("orientation", orientation.ToString())
                .ToString();
        }

        #endregion
                      
        #region IExtraPropertyCallbackRenderer Members

        private bool onDropped = false;
        private int onhidden = -1;

        public void InjectPropertyChangesToCallbackResponse(StringBuilder code)
        {
            if (onDropped)
            {
                string orient = orientation == EOrientation.Horizontal ? "left" : "top";
                int drag = int.Parse(dragger.Style[orient].Replace("px", ""));
                code.Append(".onDropped(" + drag.ToString() + ")");   
            }
            // videt
            if (onhidden == 0)
            {
                if (orientation == EOrientation.Horizontal)
                {
                    code.Append(".onShow('" + this.firstView.Width.ToString() + "px', '"
                                            + this.secondView.Width.ToString() + "px')");
                }
                else
                {
                    code.Append(".onShow('" + this.firstView.Height.ToString() + "px', '"
                                            + this.secondView.Height.ToString() + "px')");
                }
            }
            else if (onhidden == 1)
                code.Append(".onHideFirst()");

            else if (onhidden == 2)
                code.Append(".onHideSecond()");
        }

        #endregion
    }

    /// <summary>
    /// ViewPortViews
    /// </summary>
    [System.Web.UI.ParseChildren(false)]
    [System.Web.UI.PersistChildren(false)]
    [System.Web.UI.ToolboxData("<{0}:VPortView runat=\"server\"></{0}:VPortView>")]
    public class VPortView : HybridPanelBase
    {           
        [Browsable(true)]
        public new int Width 
        {
            get 
            {
                if (ViewState["w"] == null)
                    ViewState["w"] = 200;
                return (int)ViewState["w"]; 
            } 
            set 
            {                
                ViewState["w"] = value; 
            }
        }

        [Browsable(true)]
        public new int Height
        {
            get
            {
                if (ViewState["h"] == null)
                    ViewState["h"] = 200;
                return (int)ViewState["h"];
            }
            set
            {
                ViewState["h"] = value;
            }
        }

        protected override void RenderControlHtml(XhtmlTagFactory create)
        {
            using (Tag Div = create.Div(this.ClientID, this.CssClass))
            {
                Css.SerializeAttributesAndStyles(this, Div);
                RenderChildren(create.GetHtmlTextWriter());
            }
        }
    }
}
